package ui;

import infrastructure.ExceptionHandler;
import infrastructure.LoggingManager;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import application.Commands;

import communication.Communication;
import communication.ICommunication;

public class Application {

	/** Start up of the console application. 
	 * @param args
	 */
	public static void main(String[] args) {
		Logger logger = LoggingManager.CreateLogger(Application.class);
		logger.info("Starting Application");
		// Console Application. Read Option of the User
		BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
		logger.debug("Input Stream Reader created");
		boolean quit = false;
		ICommunication communication = new Communication();
		logger.debug("Communication Object created");
		Println("Welcome to EchoClient DLY. Version 1.0.");
		while(!quit)
		{			
			logger.debug("EchoClient>");
			try{			
				Print("EchoClient>");
				String inputOption = input.readLine();
				String[] tokens = inputOption.trim().split("\\s");
				if(tokens.length > 0) {
					String command = tokens[0].toLowerCase();
					logger.info("The following command was input " + command);
					
					if(command.compareTo(Commands.CONNECT) == 0){
						if (tokens.length != 3 ){
							Println("Incorrect amount of parameters");
						}
						else{
							communication.Connect(tokens[1], tokens[2]);
							Println(String.format("Connected to server %s in port %s", tokens[1], tokens[2]));
							String reply = communication.ReceiveMessage();
							Println(reply);
						}
					}
					else if(command.compareTo(Commands.DISCONNECT) == 0){
						if (tokens.length > 1 ){
							Println("Incorrect amount of parameters");
						}
						else{
							communication.Disconnect();
							Println("Disconnected");
						}
					}
					else if(command.compareTo(Commands.HELP) == 0){
						Println("This is your EchoClient application.");
						PrintHelp();
					}
					else if(command.compareTo(Commands.LOG_LEVEL) == 0){
						if ( tokens.length == 1 ){
							Println(String.format("Log Level %s", logger.getLevel()));
						} else if ( tokens.length == 2 ){
							LoggingManager.SetLoggerLevel(tokens[1]);							
							Println(String.format("New Log Level is %s", logger.getLevel()));
						} else {
							Println("Incorrect amount of parameters");
						}
							
						
					}
					else if(command.compareTo(Commands.QUIT) == 0){
						quit = true;
					}
					else if(command.compareTo(Commands.SEND) == 0){
						if (tokens.length < 2 ){
							Println("Incorrect amount of parameters");
						}
						else{
							StringBuilder message = new StringBuilder();
							for (int i=1; i < tokens.length - 1; i ++){
								message.append(tokens[i]+ " ") ;
							}
							// Add last token
							message.append(tokens[tokens.length - 1]);
									
							// Adding Carriage Return Character
							message.append('\r');						
							Println("Sending Message... ");
							communication.SendMessage(message.toString());
							String reply = communication.ReceiveMessage();
							Println(String.format("Message received: %s", reply));
						}					
					}
					else
					{
						Println("Unknown Command");
						PrintHelp();
					}
				}
			}catch(Exception ex){
				logger.error(ex);
				ExceptionHandler.Handle(ex);
			}			
		}	
		
		// Tear down the communication, in case that the client has not diconnected it.
		try{
			communication.Disconnect();
		}catch(Exception ex){
		
		}
		
		Println("Bye");
		logger.info("Application closed.");
	}
	
	public static void Print(String message){
		System.out.print(message);
	}
	
	public static void Println(String message){
		System.out.println(message);
	}

	public static void PrintHelp()
	{		
		Println("The following are the commands available:");
		Println("   " + Commands.CONNECT + " <ip address>" + " <port number>" );
		Println("   " + Commands.DISCONNECT);
		Println("   " + Commands.HELP);
		Println("   " + Commands.LOG_LEVEL + "[<New Log Level to set>]");
		Println("   " + Commands.SEND + " <message to be sent. Max size of msg 128kb");
		Println("   " + Commands.QUIT);
	}
}
